package com.vteba.security.meta;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.method.AbstractMethodSecurityMetadataSource;
import org.springframework.security.access.method.MethodSecurityMetadataSource;

import com.vteba.common.constant.CommonConst;
import com.vteba.security.spi.AuthoritiesService;
import com.vteba.security.user.Authority;
import com.vteba.security.user.Resource;

/**
 * 方法级别的权限控制，元数据加载。
 * @author yinlei
 * 2014-4-4 下午5:54:26
 */
public class MethodSecurityMetadataSourceImpl extends AbstractMethodSecurityMetadataSource implements MethodSecurityMetadataSource {
	private AuthoritiesService authoritiesServiceImpl;
	protected Map<String, Collection<ConfigAttribute>> resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
	
	public MethodSecurityMetadataSourceImpl(AuthoritiesService authoritiesServiceImpl) {
		super();
		this.authoritiesServiceImpl = authoritiesServiceImpl;
		loadMethodAuthConfig();// 加载配置
	}

	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		Set<ConfigAttribute> allAttributes = new HashSet<ConfigAttribute>();  
        for (Map.Entry<String, Collection<ConfigAttribute>> entry : resourceMap.entrySet()) {  
            allAttributes.addAll(entry.getValue());  
        }  
        return allAttributes;  
	}

	@Override
	public Collection<ConfigAttribute> getAttributes(Method method, Class<?> targetClass) {
		String methodFullPath = targetClass.getName() + CommonConst.SHARP + method.getName();
		return resourceMap.get(methodFullPath);
	}

	public void loadMethodAuthConfig() {
		List<? extends Authority> authList = authoritiesServiceImpl.getAuthorities();
		for (Authority auth : authList) {
			ConfigAttribute ca = new ConfigAttributeImpl(auth);
			List<? extends Resource> resourceList = authoritiesServiceImpl.getMethodResource(auth);
			for (Resource method : resourceList) {
				// 该资源和权限是否有对应关系，如果已经存在，则将新权限添加到对应的资源上（这个资源需要哪些权限）
				if (resourceMap.containsKey(method.getKey())) {
					Collection<ConfigAttribute> attributes = resourceMap.get(method.getKey());
					attributes.add(ca);
					resourceMap.put(method.getKey(), attributes);
				} else {// 如果是新资源，则将权限添加到对应的资源上
					Collection<ConfigAttribute> atts = new HashSet<ConfigAttribute>();
					atts.add(ca);
					resourceMap.put(method.getKey(), atts);
				}
			}
		}
	}
}
